package ebedynky.services;

import ebedynky.beans.HibernateUtil;
import ebedynky.beans.Employee;
import ebedynky.beans.Message;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Session;

/**
 * @author davidon1
 */
public class EmployeeService {

    /**
     * Seesion - current connection to the db.
     */
    private Session session;

    /**
     * Constructor, retrieves the session (connection).
     */
    public EmployeeService() {
        this.session = HibernateUtil.getSessionFactory().openSession();
    }

    /**
     * Closes the session (connection).
     * @return success/failure.
     */
    public boolean close() {
        this.session.close();
        return !(this.session.isOpen());
    }

    /**
     * Restarts the session (connection).
     * @return success/failure.
     */
    public boolean restart() {
        this.session.close();
        if (this.session.isOpen()) {
            throw new IllegalStateException("Session could not be closed.");
        }
        this.session = HibernateUtil.getSessionFactory().openSession();
        return this.session.isOpen();
    }

    /**
     * Adds Employee to the db.
     * @param emp Employee to be inserted
     * @return ID of the added Employee
     */
    public int addEmployee(Employee emp) {
        session.beginTransaction();
        int id = getMaxEmployeeID() + 1;
        emp.setEmployeeID(id);
        id = (Integer) session.save(emp);
        session.getTransaction().commit();
        return (id);
    }

    /**
     * Retrieves the maximum id currently in the database of Employees.
     * @return Max ID
     */
    public int getMaxEmployeeID() {
        String hql = "select max(u.userID) from User u";
        List list = session.createQuery(hql).list();
        if (list.get(0) != null) {
            Integer maxempid = (Integer) list.get(0);
            return maxempid;
        } else {
            return 0;
        }
    }

    /**
     * Retrieves a Employee identified by the ID.
     * @param id of the Employee
     * @return Employee with the ID given (null if not found)
     */
    public Employee getEmployeeByID(int id) {
        session.beginTransaction();
        Employee emp = (Employee) session.get(Employee.class, new Integer(id));
        session.getTransaction().commit();
        return (emp);
    }

    /**
     * Retrieves a list of all Employees stored in the db.
     * @return List of all Employees (null if no Employees)
     */
    public List<Employee> getAllEmployees() {
        session.beginTransaction();
        List<Employee> empList = session.createQuery("from Employee").list();
        session.getTransaction().commit();
        return (empList);
    }

    /**
     * Updates a specified Employee identified by ID.
     * @param newEmployee an updated Employee
     */
    public void updateEmployee(Employee newEmployee) {
        session.beginTransaction();
        Employee emp = (Employee) session.get(Employee.class, new Integer(newEmployee.getUserID()));
        emp.setAccountState(newEmployee.getAccountState());
        emp.setRoles(newEmployee.getRoles());
        emp.setStreet(newEmployee.getStreet());
        emp.setStreetNo(newEmployee.getStreetNo());
        emp.setCity(newEmployee.getCity());
        emp.setZip(newEmployee.getZip());
        emp.setEmail(newEmployee.getEmail());
        emp.setFroms(newEmployee.getFroms());
        emp.setName(newEmployee.getName());
        emp.setPass(newEmployee.getPass());
        emp.setPosition(newEmployee.getPosition());
        emp.setSurname(newEmployee.getSurname());
        emp.setTasks(newEmployee.getTasks());
        emp.setTos(newEmployee.getTos());
        emp.setUsername(newEmployee.getUsername());
        session.flush();
        session.getTransaction().commit();
        session.clear();
    }

    /**
     * Removes the Employee from db.
     * @param id Employee ID for removal
     * @return true if successful, false otherwise
     */
    public boolean deleteEmployee(int id) {
        try {
            session.beginTransaction();
            Employee emp = (Employee) session.get(Employee.class, new Integer(id));
            session.delete(emp);
            session.getTransaction().commit();
            return (true);
        } catch (HibernateException ex) {
            return (false);
        }
    }

    /**
     * Returns all messages that were aimed to this employee.
     * @param employee for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getToMessages(Employee emp) {
        if (emp == null || emp.getTos() == null || emp.getTos().isEmpty())
            return new ArrayList<Message>(0);
        return new ArrayList<Message>(emp.getTos());
    }

    /**
     * Returns all messages that were aimed to this employee.
     * @param id for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getToMessages(int id) {
        return getToMessages(getEmployeeByID(id));
    }

    /**
     * Returns all messages that were aimed from this employee.
     * @param employee for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getFromMessages(Employee emp) {
        if (emp == null || emp.getFroms() == null || emp.getFroms().isEmpty())
            return new ArrayList<Message>(0);
        return new ArrayList<Message>(emp.getFroms());
    }

    /**
     * Returns all messages that were aimed from this employee.
     * @param id for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getFromMessages(int id) {
        return getFromMessages(getEmployeeByID(id));
    }

    /**
     * Returns all messages that were aimed to/from this employee.
     * @param employee for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getAllMessages(Employee emp) {
        if (emp == null || emp.getTos() == null || emp.getTos().isEmpty())
            return new ArrayList<Message>(0);
        ArrayList<Message> am = new ArrayList<Message>(emp.getTos());
        if (emp.getFroms() != null && !emp.getFroms().isEmpty())
            am.addAll(emp.getFroms());
        return am;
    }

    /**
     * Returns all messages that were aimed to/from this employee.
     * @param id for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getAllMessages(int id) {
        return getFromMessages(getEmployeeByID(id));
    }

    /**
     * Returns all unread messages that were aimed to this employee.
     * @param employee for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getAllUnreadMessages(Employee emp) {
        if (emp == null || emp.getTos() == null || emp.getTos().isEmpty())
            return new ArrayList<Message>(0);
        ArrayList<Message> am = new ArrayList<Message>(emp.getTos());
        for (Message m : am)
            if (!m.isUnread())
                am.remove(m);
        return am;
    }

    /**
     * Returns all unread messages that were aimed to this employee.
     * @param id for whom the messages are to be found
     * @return list of messages
     */
    public List<Message> getAllUnreadMessages(int id) {
        return getAllUnreadMessages(getEmployeeByID(id));
    }
}
